package com.shihan.config;

import org.springframework.amqp.core.AcknowledgeMode;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.QueueBuilder;
import org.springframework.amqp.rabbit.annotation.EnableRabbit;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import java.net.URI;

/**
 * @Description
 * @Author shihan
 * @Date 2020/12/26 20:53
 * @Version 1.0
 */
@ComponentScan("com.shihan")    // 指明包扫描的根文件夹
@Configuration                  // 指明当前是配置类
@EnableRabbit                   // 开启注解方式的消息监听功能 即 @RabbitListener 注解  == 等价于 xml 方式的 <rabbit:annotation-driven />
public class RabbitMQConfig {

    @Bean
    public ConnectionFactory connectionFactory(){
        return new CachingConnectionFactory(URI.create("amqp://root:123456@192.168.66.129:5672/%2f"));
    }

    @Bean
    @Autowired
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory){
        return new RabbitTemplate(connectionFactory);
    }

    @Bean
    @Autowired
    public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory){
        return new RabbitAdmin(connectionFactory);
    }

    // 因为是消费者端，所以只需要关注队列即可；
    @Bean
    public Queue queue(){
        return QueueBuilder.nonDurable("queue.anno.q01").build();
    }

    /**
     * 需要添加这么一个 ListenerContainerFactory，放到 IOC 容器中的 name 必须是 rabbitListenerContainerFactory
     * 添加上这么一个 ListenerContainerFactory 后，@RabbitListener 标注的方法，其监听回调功能才算能用了
     * TODO 具体 RabbitListenerContainerFactory 的实现类，还有待研究选择，并且其内部的参数配置也还有待研究
     * @param connectionFactory
     * @return
     */
    @Bean("rabbitListenerContainerFactory")
    @Autowired
    public SimpleRabbitListenerContainerFactory simpleRabbitListenerContainerFactory(ConnectionFactory connectionFactory){
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        // 设置消息确认模式
        factory.setAcknowledgeMode(AcknowledgeMode.AUTO);
        // TODO 如果配置了并发、按批次消费，那么消息的消费顺序就会错乱，并不是按照发到队列时的顺序进行消费的，待后续深入研究！
        // 设置并发消费的常规个数 和 最大并发个数 TODO 此处设置的并发消费个数，指的具体是啥？是一个 @RabbitListener 算一个消费者吗？
        // factory.setConcurrentConsumers(10);
        // factory.setMaxConcurrentConsumers(15);
        // 按批次消费消息，每一批次发送过来的消息个数 TODO 此处的参数设置，还有待深入理解！
        // factory.setBatchSize(10);

        return factory;
    }


}
